package com.atguigu.rankinglistdemo.controller;

import com.atguigu.rankinglistdemo.dto.UserPointsReq;
import com.atguigu.rankinglistdemo.dto.UserRanking;
import jakarta.annotation.Resource;
import org.springframework.boot.autoconfigure.batch.BatchDataSource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@RestController
public class UserRankingController {

    private static final String REDTS_KEY = "user:ranking";

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 批量将用户积分数据写入到redis的zset的中
     */
    @PostMapping("/addUserPoint")
    public boolean addUserPoint(@RequestBody List<UserPointsReq> userPointsReqs){

        for (UserPointsReq userPointsReq : userPointsReqs) {
            //获取用户id
            String userId = userPointsReq.getUserId();
            //先按积分降序(从大到小),积分相同时按照最后更新时间升序(从大到小)
            //公式:score = 积分 + (1-时间戳/10的13次方)
            double score = userPointsReq.getPoints() + (1 - userPointsReq.getUpdateTime() / 1e13);

            //写入到redis中
            this.stringRedisTemplate.opsForZSet().add(REDTS_KEY,userId,score);

        }
        return true;
    }

    /**
     * 获取用户积分排行榜(倒序)
     * @param topN 排行榜的个数,前多少名
     * @return
     */
    @GetMapping("/userRankings")
    public List<UserRanking> userRankings(@RequestParam("topN") int topN){
        //获取TOPN积分排行榜从高到低
        Set<ZSetOperations.TypedTuple<String>> typedTuples =
                this.stringRedisTemplate.opsForZSet().reverseRangeWithScores(REDTS_KEY, 0, topN - 1);

        //创建一个集合放用户排行榜
        List<UserRanking> userRankingList = new ArrayList();

        for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {
            UserRanking userRanking = new UserRanking();
            userRanking.setUserId(typedTuple.getValue());
            userRanking.setRedisScore(typedTuple.getScore());
            userRankingList.add(userRanking);

        }
        return userRankingList;
    }
}
